﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace TransportationTest
{
    public class Program
    {

        private static ConcurrentDictionary<bool, int> TrafficLightDictionary = new ConcurrentDictionary<bool, int>();
        private static bool _traffic = true;//车行道红绿灯    绿灯True，红灯False   对应人行道    红灯True，绿灯False

        //车道等待队列
        private static ConcurrentQueue<Car> carsQueue = new ConcurrentQueue<Car>();
        //人道等待队列
        private static ConcurrentQueue<Person> personsQueue = new ConcurrentQueue<Person>();

        private readonly static int _carRunTime = 10;//车行45秒
        private readonly static int _personRunTime = 5;//人行30秒


        static void Main(string[] args)
        {
            TrafficLightDictionary.AddOrUpdate(_traffic, _carRunTime, (_traffic, _greenLightTime) => _greenLightTime);
            TrafficLightDictionary.AddOrUpdate(!_traffic, _personRunTime, (_traffic, _redLightTime) => _redLightTime);
            Console.ForegroundColor = ConsoleColor.Blue;
            Console.WriteLine("红绿灯初始化运行!");
            Timer TrafficLightTimer = new Timer(TrafficLightRun);
            TrafficLightTimer.Change(0, 1000);



            Task.Factory.StartNew(InitCarMode);
            Console.ForegroundColor = ConsoleColor.Blue;
            Console.WriteLine("初始化车流 模型 -完成");
            Task.Factory.StartNew(createPersonMode);
            Console.ForegroundColor = ConsoleColor.Blue;
            Console.WriteLine("初始化人流 模型 -完成");

            Thread.Sleep(1000);

            Task.Factory.StartNew(CarStart);
            Console.ForegroundColor = ConsoleColor.Blue;
            Console.WriteLine("初始化车辆通行 -完成");
            Task.Factory.StartNew(PersonStart);
            Console.ForegroundColor = ConsoleColor.Blue;
            Console.WriteLine("初始化行人通行 -完成");
            Console.ReadLine();
        }

        /// <summary>
        /// 红绿灯-Run
        /// </summary>
        /// <param name="state"></param>
        static void TrafficLightRun(object state)
        {
            TrafficLightDictionary.TryGetValue(_traffic, out int carRunTimeValue);
            TrafficLightDictionary.TryGetValue(!_traffic, out int personTimeValue);

            //Console.WriteLine($"carRunTimeValue:{carRunTimeValue}   personTimeValue:{personTimeValue}");

            //复位
            if (carRunTimeValue <= 0 && personTimeValue <= 0)
            {
                TrafficLightDictionary.AddOrUpdate(_traffic, _carRunTime, (_traffic, value) => _carRunTime);
                TrafficLightDictionary.AddOrUpdate(!_traffic, _personRunTime, (_traffic, value) => _personRunTime);
            }

            //车行
            if (carRunTimeValue > 0 && carRunTimeValue <= _carRunTime)
            {
                TrafficLightDictionary.AddOrUpdate(_traffic, carRunTimeValue, (_traffic, value) => --value);
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine($"----当前车行道---绿灯-还剩余{--carRunTimeValue}秒-");
            }
            //人行
            else if (personTimeValue > 0 && personTimeValue <= _personRunTime)
            {
                TrafficLightDictionary.AddOrUpdate(!_traffic, personTimeValue, (_traffic, Othervalue) => --Othervalue);
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine($"----当前人行道---绿灯-还剩余{--personTimeValue}秒-");
            }
        }

        /// <summary>
        /// 车行  每隔10秒模拟车进入车行道
        /// </summary>
        static async void CarStart()
        {
            while (true)
            {
                TrafficLightDictionary.TryGetValue(_traffic, out int carRunTime);
                TrafficLightDictionary.TryGetValue(!_traffic, out int personRunTime);

                //Console.WriteLine($"车辆读取value:{CarTime}");
                if (carRunTime > 0)
                {
                    List<Car> carList = new List<Car>();
                    bool run = true;
                    while (run)
                    {
                        if (carsQueue.Count > 0)
                        {
                            carsQueue.TryDequeue(out Car car);
                            carList.Add(car);
                            if (carList.Count == car.MaxParallel)
                            {
                                foreach (var item in carList)
                                {
                                    Console.ForegroundColor = ConsoleColor.Green;
                                    Console.Write($"--车行--Id:{ item.Id}, Name:{ item.Name}--\t");
                                }
                                Console.WriteLine("通行完毕");
                                carList.Clear();
                                run = false;
                            }
                            else
                            {
                                TrafficLightDictionary.TryGetValue(_traffic, out int newCarRunTime);
                                if (newCarRunTime <= 0)
                                {
                                    break;
                                }
                            }
                        }
                        else if (carList.Count > 0)
                        {
                            foreach (var item in carList)
                            {
                                Console.ForegroundColor = ConsoleColor.Green;
                                Console.Write($"--车行--Id:{ item.Id}, Name:{ item.Name}--\t");
                            }
                            carList.Clear();
                            Console.WriteLine("通行完毕");
                        }
                    }
                }
                await Task.Delay(500);
            }
        }

        /// <summary>
        /// 人行
        /// </summary>
        static async void PersonStart()
        {
            while (true)
            {
                TrafficLightDictionary.TryGetValue(!_traffic, out int personRunTime);
                TrafficLightDictionary.TryGetValue(_traffic, out int carRunTime);
                //Console.WriteLine($"carRunTime:{carRunTime}   personTime:{personTime}");
                List<Person> persons = new List<Person>();
                if (carRunTime <= 0 && personRunTime > 0)
                {
                    bool run = true;
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.WriteLine("行人通行中");
                    while (run)
                    {
                        if (personsQueue.Count > 0)
                        {
                            personsQueue.TryDequeue(out Person person);
                            persons.Add(person);
                            if (persons.Count == person.MaxParallel)
                            {
                                foreach (var item in persons)
                                {
                                    Console.ForegroundColor = ConsoleColor.Yellow;
                                    Console.Write($"--人行--Id:{ item.Id}, Name:{ item.Name}--\t");
                                }
                                persons.Clear();
                                run = false;
                            }
                            else
                            {
                                TrafficLightDictionary.TryGetValue(!_traffic, out int newPersonRunTime);
                                TrafficLightDictionary.TryGetValue(_traffic, out int newCarRunTime);
                                if (newCarRunTime > 0 || newPersonRunTime <= 0)
                                {
                                    break;
                                }
                            }
                        }
                        else if (persons.Count > 0)
                        {
                            foreach (var item in persons)
                            {
                                Console.ForegroundColor = ConsoleColor.Yellow;
                                Console.Write($"--人行--Id:{ item.Id}, Name:{ item.Name}--\t");
                            }
                            persons.Clear();
                            Console.WriteLine("通行完毕");
                        }
                    }
                }
                await Task.Delay(500);
            }
        }

        /// <summary>
        /// 初始化 车流模型
        /// </summary>
        static async void InitCarMode()
        {
            while (true)
            {
                // 车的数量随机
                Random random = new Random();
                var carCount = random.Next(10, 50);
                Console.WriteLine($"推入车流量 {carCount}人");
                List<Task> taskFactories = new List<Task>();
                for (int i = 0; i < carCount; i++)
                {

                    Car inQueueCar = new Car()
                    {
                        Id = Guid.NewGuid().ToString(),
                        Name = "模拟车辆" + i,
                        MaxParallel = 4
                    };
                    Task task = new Task(() =>
                    {
                        CarInQueue(inQueueCar);
                    });
                    taskFactories.Add(task);
                    task.Start();
                }
                await Task.WhenAll(taskFactories.ToArray());
                // Console.WriteLine("--入队完成--");
                await Task.Delay(10 * 1000);
            }
        }

        /// <summary>
        /// 初始化 人流模型
        /// </summary>
        static async void createPersonMode()
        {
            while (true)
            {
                // 人的数量随机
                Random random = new Random();
                var personCount = random.Next(10, 40);
                Console.WriteLine($"推入人流量 {personCount}人");
                List<Task> taskFactories = new List<Task>();
                for (int i = 0; i < personCount; i++)
                {

                    Person inQueuePerson = new Person()
                    {
                        Id = Guid.NewGuid().ToString(),
                        Name = "模拟行人" + i,
                        MaxParallel = 5
                    };
                    Task task = new Task(() =>
                    {
                        PersonInQueue(inQueuePerson);
                    });
                    taskFactories.Add(task);
                    task.Start();
                }
                await Task.WhenAll(taskFactories.ToArray());
                // Console.WriteLine("--入队完成--");
                await Task.Delay(10 * 1000);
            }
        }

        /// <summary>
        /// 车 入队
        /// </summary>
        static void CarInQueue<T>(T inQueueItem) where T : Car
        {
            carsQueue.Enqueue(inQueueItem);
            //Console.WriteLine("人流 进入等待队列");
        }

        /// <summary>
        /// 人 入队
        /// </summary>
        static void PersonInQueue<T>(T inQueueItem) where T : Person
        {
            personsQueue.Enqueue(inQueueItem);
            //Console.WriteLine("车流 进入等待队列");
        }

    }
}
